package com.chenbei.common.config;

import cn.hutool.core.util.StrUtil;
import com.chenbei.common.properties.RedissonProperties;
import lombok.extern.slf4j.Slf4j;
import org.redisson.Redisson;
import org.redisson.api.RedissonClient;
import org.redisson.client.codec.StringCodec;
import org.redisson.config.Config;
import org.redisson.config.ReadMode;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

@Configuration
@Slf4j
public class RedissonConfig {

    private final static String ADDRESS_PREFIX = "redis://";

    @Autowired
    private RedissonProperties redissonProperties;

    @Bean
    public RedissonClient redissonClient() {
        if (StrUtil.isNotBlank(redissonProperties.getSentinelMaster()) && StrUtil.isNotBlank(redissonProperties.getSentinelNodes())) {
            return sentinelMode();
        }
        if (StrUtil.isNotBlank(redissonProperties.getCluster())) {
            return clusterMode();
        }
        if (StrUtil.isNotBlank(redissonProperties.getHost())) {
            return singleMode();
        }
        log.error("redisson config can not support this redis mode");
        return null;
    }

    private RedissonClient sentinelMode() {
        List<String> nodeList = Arrays.stream(redissonProperties.getSentinelNodes().split(",")).map(node -> ADDRESS_PREFIX + node).collect(Collectors.toList());
        Config config = new Config();
        config.setCodec(new StringCodec())
                .useSentinelServers()
                .setMasterName(redissonProperties.getSentinelMaster())
                .setPassword(redissonProperties.getPassword())
                .setTimeout(redissonProperties.getTimeout())
                .addSentinelAddress(nodeList.toArray(new String[]{}))
                .setCheckSentinelsList(false);
        return Redisson.create(config);
    }

    private RedissonClient clusterMode() {
        List<String> nodeList = Arrays.stream(redissonProperties.getCluster().split(",")).map(node -> ADDRESS_PREFIX + node).collect(Collectors.toList());
        Config config = new Config();
        config.setCodec(new StringCodec())
                .useClusterServers()
                .addNodeAddress(nodeList.toArray(new String[]{}))
                .setScanInterval(redissonProperties.getScanInterval())
                .setPassword(redissonProperties.getPassword())
                .setReadMode(ReadMode.MASTER);

        return Redisson.create(config);
    }

    private RedissonClient singleMode() {
        Config config = new Config();
        config.setCodec(new StringCodec())
                .useSingleServer()
                .setAddress(ADDRESS_PREFIX + redissonProperties.getHost() + ":" + redissonProperties.getPort())
                .setPassword(redissonProperties.getPassword())
                .setTimeout(redissonProperties.getTimeout());

        return Redisson.create(config);
    }
}
